<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">

<script>
    (function(){
        if(''){
            if (prompt('请输入文章密码') !== ''){
                alert('密码错误！');
                history.back();
            }
        }
    })();
</script>

  <script>
  (function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/0f81ff2f.js","daovoice")
  daovoice('init', {
      app_id: "456d7aa2"
    });
  daovoice('update');
  </script>



  
  
    
    
  <script src="/lib/pace/pace.min.js?v=1.0.2"></script>
  <link href="/lib/pace/pace-theme-minimal.min.css?v=1.0.2" rel="stylesheet">







<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.2" rel="stylesheet" type="text/css">


  <meta name="keywords" content="JVM,GC,内存分配策略,">





  <link rel="alternate" href="/atom.xml" title="Elvis's Blogs" type="application/atom+xml">




  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.2">






<meta name="description" content="​        最近在看周志明老师的《深入理解Java虚拟机》，准备留下一些学习笔记，供以后复习用。以下内容主要来自于《深入理解Java虚拟机》第三章–垃圾收集器与内存分配策略。  一 学习目标 对象存活判断算法  GC（garbage collection）算法学习  垃圾回收器  内存分配与回收策略   对于GC学习,我们主要考虑三个问题：哪些内存需要回收 -&amp;gt; 什么时候回收 -&amp;g">
<meta name="keywords" content="JVM,GC,内存分配策略">
<meta property="og:type" content="article">
<meta property="og:title" content="垃圾收集器与内存分配策略-深入理解JVM">
<meta property="og:url" content="https://www.vazh.cn/2019/08/29/垃圾收集器与内存分配策略-深入理解JVM/index.html">
<meta property="og:site_name" content="Elvis&#39;s Blogs">
<meta property="og:description" content="​        最近在看周志明老师的《深入理解Java虚拟机》，准备留下一些学习笔记，供以后复习用。以下内容主要来自于《深入理解Java虚拟机》第三章–垃圾收集器与内存分配策略。  一 学习目标 对象存活判断算法  GC（garbage collection）算法学习  垃圾回收器  内存分配与回收策略   对于GC学习,我们主要考虑三个问题：哪些内存需要回收 -&amp;gt; 什么时候回收 -&amp;g">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc01.webp">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc02.webp">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc03.webp">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc04.webp">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc10.png">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc11.png">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc05.webp">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc06.webp">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc07.webp">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc08.webp">
<meta property="og:image" content="https://www.vazh.cn/picture/GC/gc09.webp">
<meta property="og:updated_time" content="2020-08-10T06:45:21.775Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="垃圾收集器与内存分配策略-深入理解JVM">
<meta name="twitter:description" content="​        最近在看周志明老师的《深入理解Java虚拟机》，准备留下一些学习笔记，供以后复习用。以下内容主要来自于《深入理解Java虚拟机》第三章–垃圾收集器与内存分配策略。  一 学习目标 对象存活判断算法  GC（garbage collection）算法学习  垃圾回收器  内存分配与回收策略   对于GC学习,我们主要考虑三个问题：哪些内存需要回收 -&amp;gt; 什么时候回收 -&amp;g">
<meta name="twitter:image" content="https://www.vazh.cn/picture/GC/gc01.webp">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://www.vazh.cn/2019/08/29/垃圾收集器与内存分配策略-深入理解JVM/">





  <title>垃圾收集器与内存分配策略-深入理解JVM | Elvis's Blogs</title>
  














</head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <a href="https://github.com/zkstyle" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewbox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>


    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Elvis's Blogs</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">研一狗的日常</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://www.vazh.cn/2019/08/29/垃圾收集器与内存分配策略-深入理解JVM/">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="zkstyle">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/zhihu02.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Elvis's Blogs">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">垃圾收集器与内存分配策略-深入理解JVM</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-08-29T19:56:03+08:00">
                2019-08-29
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope="" itemtype="http://schema.org/Thing">
                  <a href="/categories/深入理解JVM/" itemprop="url" rel="index">
                    <span itemprop="name">深入理解JVM</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          
             <span id="/2019/08/29/垃圾收集器与内存分配策略-深入理解JVM/" class="leancloud_visitors" data-flag-title="垃圾收集器与内存分配策略-深入理解JVM">    
	       | &nbsp;
               <span class="post-meta-divider"></span>
               <span class="post-meta-item-icon">
                 <i class="fa fa-eye"></i>
               </span>
               
                 <span class="post-meta-item-text">热度 </span>
               
                 <span class="leancloud-visitors-count"></span>
		 <span>℃ </span>
             </span>
          

          

          
	    <br>
            <div class="post-wordcount">
              
		&nbsp;
                
		
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计</span>
                
                <span title="字数统计">
                  6,875 字
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长</span>
                
                <span title="阅读时长">
                  ≈24 分钟
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <blockquote>
<p>​        最近在看周志明老师的《深入理解Java虚拟机》，准备留下一些学习笔记，供以后复习用。以下内容主要来自于《深入理解Java虚拟机》第三章–垃圾收集器与内存分配策略。</p>
</blockquote>
<h2 id="一-学习目标"><a href="#一-学习目标" class="headerlink" title="一 学习目标"></a>一 学习目标</h2><ol>
<li><p>对象存活判断算法</p>
</li>
<li><p>GC（garbage collection）算法学习</p>
</li>
<li><p>垃圾回收器</p>
</li>
<li><p>内存分配与回收策略</p>
</li>
</ol>
<p><strong>对于GC学习,我们主要考虑三个问题：哪些内存需要回收 -&gt; 什么时候回收 -&gt; 如何回收</strong></p>
<h2 id="二-那些内存需要回收"><a href="#二-那些内存需要回收" class="headerlink" title="二 那些内存需要回收"></a>二 那些内存需要回收</h2><p>  内存运行时，程序计数器、本地方法栈和虚拟机栈是随着线程的产生而产生，随着线程的消亡而消亡的，这几部分的内存分配和回收是确定好了的，随方法结束或线程结束时，内存就紧跟着回收了。而Java堆和方法区不一样。一个接口中多个实现类需要的内存可能不一样，一个方法中的多个分支需要的内存也可能不一样，我们只有在运行期间才知道会创建哪些对象，故内存回收与分配重点关注的是<strong>堆内存</strong>和<strong>方法区内存。</strong></p>
<h2 id="三-什么时候回收（判断对象的存活）"><a href="#三-什么时候回收（判断对象的存活）" class="headerlink" title="三.什么时候回收（判断对象的存活）"></a>三.什么时候回收（判断对象的存活）</h2><p><strong>对于方法区</strong>，永久代的垃圾收集主要回收两部分内容：废弃常量和无用的类。</p>
<p><strong>对于堆</strong>，其中存放的是对象实例，对于对象实例的回收，我们首先要判断哪些对象是“存活的”，对于那部分“死亡的”对象，就是我们要回收的。判断对象的存活有两种方法：</p>
<ul>
<li>引用计数算法</li>
<li>可达性分析算法</li>
</ul>
<h3 id="引用计数算法"><a href="#引用计数算法" class="headerlink" title="引用计数算法"></a>引用计数算法</h3><p>给对象添加一个引用计数器, 每当有一个地方引用它时, 计数器值+1, 引用失效, -1, 为0的对象不能被使用。</p>
<ul>
<li>优势：实现简单，效率高。</li>
<li>缺点：无法解决对象相互引用的问题——会导致对象的引用虽然存在，但是已经不可能再被使用，却无法被回收。</li>
</ul>
<h3 id="可达性分析算法"><a href="#可达性分析算法" class="headerlink" title="可达性分析算法"></a>可达性分析算法</h3><p>通过一系列的称为“GC Roots”的对象作为起始点, 从这些节点开始向下搜索, 搜索走过的路径称为引用链(Reference Chain), 当一个对象到GC Roots不可达(也就是不存在引用链)的时候, 证明对象是不可用的。如下图: <em>Object5、6、7</em> 虽然互有关联, 但它们到GC Roots是不可达的, 因此也会被判定为可回收的对象。（注意：不可达的对象, VM也并不是马上对其回收, 因为要真正宣告一个对象死亡, 至少要经历两次标记）</p>
<p><img src="/picture/GC/gc01.webp" alt="img"></p>
<p>在Java, 可作为GC Roots的对象包括：</p>
<ul>
<li>方法区: 类静态属性引用的对象;</li>
<li>方法区: 常量引用的对象;</li>
<li>虚拟机栈(本地变量表)中引用的对象.</li>
<li>本地方法栈JNI(Native方法)中引用的对象。</li>
</ul>
<h2 id="四-如何回收-垃圾收集算法"><a href="#四-如何回收-垃圾收集算法" class="headerlink" title="四 如何回收-垃圾收集算法"></a>四 如何回收-垃圾收集算法</h2><h3 id="1-标记清除算法"><a href="#1-标记清除算法" class="headerlink" title="1.标记清除算法"></a>1.标记清除算法</h3><p>  分为标记和清除两个阶段，先标记出需要回收的对象（可达性分析算法或者引用计数算法），在标记完成后统一回收所有被标记的对象。</p>
<p>  不足之处：效率问题，标记和清除效率都不高。空间问题，标记清除之后会产生大量不连续的内存碎片，空间碎片太多可能会导致以后在程序运行过程中分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作。</p>
<p><img src="/picture/GC/gc02.webp" alt="img"></p>
<h3 id="2-复制算法"><a href="#2-复制算法" class="headerlink" title="2.复制算法"></a>2.复制算法</h3><p>  将可用内存划分为大小相等的两块，每次只使用其中的一块。当这块用完了，就将还存活的复制到另一块上，然后将这一块一次性清除。商业虚拟机都是采用该方法来回收新生代，新生代98%都是朝生夕死的。将内存分为较大Eden和两个较小的survivor空间。每次使用其中一块Eden和survivor，回收时将存活的对象一次性地复制到另一块survivor中，再清理掉之前的。HotSpot虚拟机Eden与Survivor默认的大小比例为8:1:1。survivor空间不够时，需要依赖其他内存（老年代）进行分配担保，即让对象进入老年代。</p>
<p><img src="/picture/GC/gc03.webp" alt="img"></p>
<p>3.标记整理算法</p>
<p>  复制在对象存活率较高时效率很低。根据老年代的特点提出该算法。标记过程同标记清除一样，但不是直接对可回收对象进行清理，而是让存活对象朝着一端移动，然后直接清理掉端边界外的内存。</p>
<p><img src="/picture/GC/gc04.webp" alt="img"></p>
<h3 id="4-分代收集算法"><a href="#4-分代收集算法" class="headerlink" title="4.分代收集算法"></a>4.分代收集算法</h3><p>  根据各年代特点分别采用最适当的GC算法。在新生代:中每次垃圾收集都能发现大批对象已死, 只有少量存活. 因此选用复制算法, 只需要付出少量存活对象的复制成本就可以完成收集。在老年代: 因为对象存活率高、没有额外空间对它进行分配担保, 就必须采用<strong>“</strong>标记—清理<strong>”</strong>或<strong>“</strong>标记—整理<strong>”</strong>算法来进行回收, 不必进行内存复制, 且直接腾出空闲内存。即：</p>
<ul>
<li>新生代：存活率低，使用复制算法</li>
<li>老年代：存活率高，使用“标记-整理”或“标记-清除”算法</li>
</ul>
<h2 id="五-Hotspot算法实现及准确式GC"><a href="#五-Hotspot算法实现及准确式GC" class="headerlink" title="五 Hotspot算法实现及准确式GC"></a>五 Hotspot算法实现及准确式GC</h2><blockquote>
<p> 上面讲到了Java虚拟机是如何利用可达性算法判断对象是否需要回收的，由于在GC进行时，必须暂停所有的Java执行线程（Sun称之为“Stop The World”），所以，虚拟机必须尽量的优化GC过程的效率，减少暂停的时间。那么对于GC Roots，HotSpot是如何快速确定的呢？</p>
</blockquote>
<h3 id="对象的创建"><a href="#对象的创建" class="headerlink" title="对象的创建"></a>对象的创建</h3><p>首先，我们需要知道在JVM中，对象是如何被创建的。</p>
<p>而对象的创建通常是通过new一个对象而已，当虚拟机接收到一个new指令时，它会做如下的操作:</p>
<h4 id="1-判断对象对应的类是否加载、链接、初始化"><a href="#1-判断对象对应的类是否加载、链接、初始化" class="headerlink" title="1 判断对象对应的类是否加载、链接、初始化"></a>1 判断对象对应的类是否加载、链接、初始化</h4><p>虚拟机接收到一条new指令时，首先会去检查这个指定的参数是否能在常量池中定位到一个类的符号引用，并且检查这个符号引用代表的类是否已被类加载器加载、链接和初始化过。如果没有则先执行相应的类加载过程。关于类加载器我们在前一篇文章中已经提到过，这里不再赘述。</p>
<h4 id="2为对象分配内存"><a href="#2为对象分配内存" class="headerlink" title="2为对象分配内存"></a>2为对象分配内存</h4><p>类加载完成后，接着会在Java堆中划分一块内存分配给对象。内存分配根据Java堆是否规整，有两种方式：</p>
<p>指针碰撞：如果Java堆的内存是规整，即所有用过的内存放在一边，而空闲的的放在另一边。分配内存时将位于中间的指针指示器向空闲的内存移动一段与对象大小相等的距离，这样便完成分配内存工作。</p>
<p>空闲列表：如果Java堆的内存不是规整的，则需要由虚拟机维护一个列表来记录那些内存是可用的，这样在分配的时候可以从列表中查询到足够大的内存分配给对象，并在分配后更新列表记录。</p>
<h4 id="3处理并发安全问题"><a href="#3处理并发安全问题" class="headerlink" title="3处理并发安全问题"></a>3处理并发安全问题</h4><p>创建对象是一个非常频繁的操作，所以需要解决并发的问题，有两种方式：</p>
<p>对分配内存空间的动作进行同步处理，比如在虚拟机采用CAS算法并配上失败重试的方式保证更新操作的原子性。</p>
<p>每个线程在Java堆中预先分配一小块内存，这块内存称为本地线程分配缓冲（Thread Local Allocation Buffer）简写为TLAB，线程需要分配内存时，就在对应线程的TLAB上分配内存，当线程中的TLAB用完并且被分配到了新的TLAB时，这时候才需要同步锁定。通过-XX:+/-UserTLAB参数来设定虚拟机是否使用TLAB。</p>
<h4 id="4初始化分配到的内存空间"><a href="#4初始化分配到的内存空间" class="headerlink" title="4初始化分配到的内存空间"></a>4初始化分配到的内存空间</h4><p>将分配到的内存，除了对象头都初始化为零值。</p>
<h4 id="5设置对象的对象头"><a href="#5设置对象的对象头" class="headerlink" title="5设置对象的对象头"></a>5设置对象的对象头</h4><p>将对象的所属类、对象的HashCode和对象的GC分代年龄等数据存储在对象的对象头中。</p>
<h4 id="6执行init方法进行初始化"><a href="#6执行init方法进行初始化" class="headerlink" title="6执行init方法进行初始化"></a>6执行init方法进行初始化</h4><p>执行init方法，初始化对象的成员变量、调用类的构造方法，这样一个对象就被创建了出来。</p>
<p>对象的堆内存布局<br>在HotSpot虚拟机中，对象在堆内存的布局分为三个区域，分别是对象头（Header）、实例数据（Instance Data）、对齐填充（Padding）。</p>
<p>对象头：对象头包括两部分信息分别是Mark World和元数据指针，Mark World用于存储对象运行时的数据，比如HashCode、锁状态标志、GC分代年龄等。而元数据指针用于指向方法区的中目标类的类型信息，通过元数据指针可以确定对象的具体类型。</p>
<p>实例数据：用于存储对象中的各种类型的字段信息（包括从父类继承来的）。</p>
<p>对齐填充：对齐填充不一定存在，起到了占位符的作用，没有特别的含义。</p>
<p>对象分配如下图所示：</p>
<p><img src="/picture/GC/gc10.png" alt=""></p>
<h3 id="HotSpot的对象模型"><a href="#HotSpot的对象模型" class="headerlink" title="HotSpot的对象模型"></a>HotSpot的对象模型</h3><p>HotSpot中采用了OOP-Klass模型，它是用来描述Java对象实例的一种模型，OOP（Ordinary Object Pointer）指的是普通对象指针，而Klass用来描述对象实例的具体类型。</p>
<p>HotSpot中，用instanceOopDesc 和 arrayOopDesc 来描述对象头，其中arrayOopDesc对象用于描述数组类型。</p>
<p>通过OOP-Klass模型，我们就知道了Java虚拟机是如何通过栈帧中的对象引用找到对应的对象实例，如下图所示：</p>
<p><img src="/picture/GC/gc11.png" alt=""></p>
<p>从图中可以看出，通过栈帧中的对象引用找到Java堆中的instanceOopDesc对象，再通过instanceOopDesc中的元数据指针来找到方法区中的instanceKlass，从而确定该对象的具体类型。</p>
<h3 id="HotSpot的准确式GC"><a href="#HotSpot的准确式GC" class="headerlink" title="HotSpot的准确式GC"></a>HotSpot的准确式GC</h3><p>HotSpot采用了准确式GC以提升GC roots的枚举速度。所谓准确式GC，就是让JVM知道内存中某位置数据的类型什么。比如当前内存位置中的数据究竟是一个整型变量还是一个引用类型。这样JVM可以很快确定所有引用类型的位置，从而更有针对性的进行GC roots枚举。</p>
<p>HotSpot是利用OopMap来实现准确式GC的。当类加载完成后，HotSpot 就将对象内存布局之中什么偏移量上数值是一个什么样的类型的数据这些信息存放到 OopMap 中；在 HotSpot 的 JIT 编译过程中，同样会插入相关指令来标明哪些位置存放的是对象引用等，这样在 GC 发生时，HotSpot 就可以直接扫描 OopMap 来获取对象引用的存储位置，从而进行 GC Roots 枚举。</p>
<h3 id="HotSpot安全点"><a href="#HotSpot安全点" class="headerlink" title="HotSpot安全点"></a>HotSpot安全点</h3><p>通过OopMap，HotSpot可以很快完成GC Roots的查找，但是，如果在每一行代码都有可能发生GC，那么也就意味着得为每一行代码的指令都生成OopMap，这样将占用大量的空间。实际上，HotSpot也不会这么做。</p>
<p>HotSpot只在特定的位置记录了OopMap，这些位置就叫做安全点（Safepoint），也就是说，程序并不能在任意地方都可以停下来进行GC，只有到达安全点时才能暂停进行GC。</p>
<p>在安全点中，HotSpot也会开始记录虚拟机的相关信息，如OopMap信息的录入。安全点的选择不能太少，否则GC等待时间太长；也不能太多，否则会增大运行负荷，其选择的原则为“是否具有让程序长时间执行的特征”，如方法调用，循环等等。具体安全点有下面几个：</p>
<p>(1) 循环的末尾 (防止大循环的时候一直不进入Safepoint，而其他线程在等待它进入Safepoint)<br>(2) 方法返回前<br>(3) 调用方法的call之后<br>(4) 抛出异常的位置</p>
<p>而安全点暂停线程运行的手段有两种：抢先式中断和主动式中断。</p>
<h3 id="抢先式中断"><a href="#抢先式中断" class="headerlink" title="抢先式中断"></a>抢先式中断</h3><p>不需要线程的执行代码主动配合，在GC发生时，首先把所有线程全部中断，如果发现有线程中断的地方不在安全点上，就恢复线程，让它跑到安全点上再暂停。不过现在的虚拟机几乎没有采用此算法的。</p>
<h3 id="主动式中断"><a href="#主动式中断" class="headerlink" title="主动式中断"></a>主动式中断</h3><p>GC需要中断线程的时候，不直接对线程操作，仅仅简单地设置一个标志，各个线程执行时去主动轮询查询此标志，发现中断标志为真时就中断自己挂起。轮询标志的地方和安全点是重合的，另外再加上创建对象需要分配内存的地方。</p>
<h3 id="HotSpot安全区域"><a href="#HotSpot安全区域" class="headerlink" title="HotSpot安全区域"></a>HotSpot安全区域</h3><p>产生原因<br>安全点机制保证了程序执行时进入GC的问题。但是对于非执行态下，如线程Sleep或者Block下，由于此时程序（线程）无法响应JVM的中断请求，JVM也不太可能一直等待线程重新获取时间片，此时就需要安全区域(Safe Region)了。安全区域是指在一段代码片段内，引用关系不会发生变化，在这段区域内，任意地方开始GC都是安全的。</p>
<p>运行机理<br>在线程执行到Safe Region中的代码时，首先标识自己已经进入了Safe Region。当在这段时间里JVM要发起GC时，就不用管标识自己为Safe Region状态的线程了；当线程要离开Safe Region时，如果整个GC完成，那线程可继续执行，否则它必须等待直到收到可以安全离开Safe Region的信号为止。</p>
<h2 id="六-七种垃圾收集器"><a href="#六-七种垃圾收集器" class="headerlink" title="六 七种垃圾收集器"></a>六 七种垃圾收集器</h2><p>重点笔记：</p>
<ul>
<li>并行（Parallel）：多条垃圾收集线程</li>
<li>并发（Concurrent）：用户线程与垃圾收集线程同时执行（但不一定是并行，可能会交替执行），用户线程在继续运行，而垃圾收集程序运行于另外一个CPU上。</li>
<li>新生代：Serial收集器　　ParNew收集器　　Parallel Scavenge收集器</li>
<li>老年代：Serial Old收集器　　Parallel Old收集器　　CMS收集器</li>
</ul>
<p><img src="/picture/GC/gc05.webp" alt=""></p>
<h3 id="新生代垃圾收集器"><a href="#新生代垃圾收集器" class="headerlink" title="新生代垃圾收集器"></a>新生代垃圾收集器</h3><h4 id="1-Serial收集器"><a href="#1-Serial收集器" class="headerlink" title="1.Serial收集器"></a>1.Serial收集器</h4><p>  最悠久，最基本的收集器；<strong>单线程</strong>收集器，只使用一个CPU或一条收集线程去完成垃圾收集工作，且在收集时，必须暂停其他所有的工作线程，直到收集结束。<strong>新生代采取复制算法</strong>。老年代采取标记整理算法。在进行垃圾收集时必须暂停其他所有的工作线程，即“Stop The World”。依然是虚拟机运行在Client模式下的默认新生代收集器。Serial一般在单核的机器上使用，是Java 5非服务端JVM的默认收集器。</p>
<blockquote>
<ol>
<li>新生代：单线程复制收集算法；</li>
<li>老年代：单线程标记整理算法。</li>
<li>参数-XX:UseSerialGC设置使用</li>
</ol>
<p>优势：对于单CPU环境来说，Serial收集器没有线程交互的开销，专心做垃圾收集可以获得最高的单线程收集。Serial收集器对于在Client模式下的虚拟机是一个很好的选择。 </p>
</blockquote>
<p><img src="/picture/GC/gc06.webp" alt=""></p>
<h4 id="2-ParNew收集器"><a href="#2-ParNew收集器" class="headerlink" title="2.ParNew收集器"></a>2.ParNew收集器</h4><p>  Serial收集器的多线程版。<strong>多条线程</strong>进行垃圾收集，采用<strong>复制算法</strong>。其余和Serial收集器一样。目前唯一能与CMS收集器配合工作。ParNew收集器在单CPU环境中不比Serial效果好，甚至可能更差，两个CPU也不一定跑的过，但随着CPU数量的增加，性能会逐步增加。默认开启的收集线程数与CPU数量相同。在CPU数量很多的情况下，可以使用-XX:ParallelGCThreads参数来限制线程数。</p>
<blockquote>
<ol>
<li>新生代并行，老年代串行</li>
<li>新生代复制算法、老年代标记-整理</li>
<li>参数控制：<br>-XX:+UseConcMarkSweepGC”：指定使用CMS后，会默认使用ParNew作为新生代收集器；<br>-XX:+UseParNewGC”：强制指定使用ParNew；<br>-XX:ParallelGCThreads”：指定垃圾收集的线程数量，ParNew默认开启的收集线程与CPU的数量相同；</li>
</ol>
<p>优势：ParNew收集器是许多运行在server模式下的虚拟机中首选的新生代收集器，一个重要的原因是，只有ParNew和Serial收集器能和CMS收集器共同工作。无法与JDK1.4中存在的新生代收集器Parallel Scavenge配合工作，所以在JDK1.5中使用CMS来收集老年代的时候，新生代只能选择ParNew和Serial。</p>
</blockquote>
<p><img src="/picture/GC/gc07.webp" alt=""></p>
<h4 id="3-Parallel-Scavenge收集器"><a href="#3-Parallel-Scavenge收集器" class="headerlink" title="3.Parallel Scavenge收集器"></a>3.Parallel Scavenge收集器</h4><p>  新生代收集器，<strong>多线程并行</strong>、使用<strong>复制算法</strong>。</p>
<p>  CMS的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间，而PS收集器的目的则是达到一个可控制的吞吐量。吞吐量即CPU用于运行用户代码的时间与CPU总消耗时间的比值（吞吐量=运行用户代码的时间/（运行用户代码的时间+垃圾收集的时间））。</p>
<blockquote>
<p>使用-XX:MaxGCPauseMillus参数控制垃圾停顿时间</p>
<p>使用-XX:GCTimeRatio参数控制吞吐量。</p>
<p>Parallel Scavenge收集器设置-XX:UseAdaptiveSizePolicy参数，虚拟机会根据当前系统的运行情况收集性能监控信息，动态调整这些参数以提供最合适的停顿时间或者最大吞吐量（GC自使用的调节策略）。<br>自适应调节策略也是Parallel Scavenge收集器和ParNew收集器一个重要的区别。</p>
</blockquote>
<p><img src="/picture/GC/gc08.webp" alt=""></p>
<h3 id="老年代垃圾收集器"><a href="#老年代垃圾收集器" class="headerlink" title="老年代垃圾收集器"></a>老年代垃圾收集器</h3><h4 id="4-Serial-Old收集器"><a href="#4-Serial-Old收集器" class="headerlink" title="4.Serial Old收集器"></a>4.Serial Old收集器</h4><p>  Serial Old同样是<strong>单线程</strong>收集器,使用“<strong>标记-整理</strong>”算法。可以与JDK1.5及之前的Parallel Scavenge搭配使用；也可以作为CMS收集器的后备预案，在并发收集发生Concureent Mode Failure时使用。</p>
<h4 id="5-Parallel-Old收集器"><a href="#5-Parallel-Old收集器" class="headerlink" title="5.Parallel Old收集器"></a>5.Parallel Old收集器</h4><p>  Parallel Old收集器是<strong>多线程</strong>，使用“<strong>标记-整理</strong>”算法。</p>
<p>  JDK1.6前，Parallel Scavenge只能与老年代收集器Serial Old（PS MarkSweep）组合，由于Serial Old无法充分利用服务器多CPU的处理能力，会拖累整体性能。</p>
<p>  JDK1.6后，Parallel Scavenge可与Parallel Old组合，达到名副其实的“吞吐量优先”，在注重吞吐量以及CPU资源敏感的场合可以优先考虑这个组合。</p>
<h4 id="6-CMS收集器"><a href="#6-CMS收集器" class="headerlink" title="6.CMS收集器"></a>6.CMS收集器</h4><p>  基于“<strong>标记—清除</strong>”算法，低停顿，<strong>并发收集</strong>。以获取最短回收停顿时间、低延迟为目标，适用于重视服务响应速度的应用。</p>
<p>主要过程为一下四步：</p>
<ul>
<li>初始标记；Stop the World，仅标记GCRoots能关联的对象，速度很快。</li>
<li>并发标记；进行GCRootsTracing的过程。</li>
<li>重新标记；修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录。比1长但远比2短。</li>
<li>并发清除；并发清除与并发标记耗时最长。收集器线程都可以与用户线程一起工作。并发清理以后重置线程。</li>
</ul>
<p><strong>CMS收集器的内存回收过程是与用户线程一起并发执行的</strong></p>
<p><strong>主要缺点：</strong></p>
<ul>
<li>CMS收集器对CPU资源非常敏感。在并发阶段，它虽然不会导致用户线程停顿，但是因为占用了一部分CPU资源而导致应用程序变慢，总吞吐量就会降低。CMS默认启动的回收线程数为(CPU数量+3)/4。当CPU的个数少于2个的时候，CMS对用户程序的影响可能会变得很大。</li>
<li>CMS收集器<strong>无法处理浮动垃圾（floating garbage）</strong>，可能会出现concurrent mode failure导致另一次full gc的产生。在CMS的并发清理阶段，由于程序还在运行，垃圾还会不断产生，这一部分垃圾出现在标记过程之后，CMS无法在本次收集中处理掉它们，只好留到下一次GC再处理。这种垃圾称为浮动垃圾。同样由于CMS GC阶段用户线程还需要运行，即还需要预留足够的内存空间供用户线程使用，因此CMS收集器不能像其他收集器那样等到老年代几乎完全被灌满了再进行收集而需要预留一部分空间提供并发收集时的程序运作使用。<strong>默认设置下 CMS收集器在老年代使用了68%的空间后就会被激活</strong>。这个值可以用-XX:CMSInitiatingOccupancyFraction来设置。要是CMS运行期间预留的内存无法满足程序需要，就会出现concurrent mode failure，这时候就会启用Serial Old收集器作为备用进行老年代的垃圾收集。</li>
<li>空间碎片过多（标记-清除算法的弊端），CMS是基于标记-清除算法来实现的回收器，提供-XX:+UseCMSCompactAtFullCollection参数，应用于在FULL GC后再进行一个碎片整理过程。-XX:CMSFullGCsBeforeCompaction,多少次不压缩的full gc后来一次带压缩的。</li>
</ul>
<p><img src="/picture/GC/gc09.webp" alt=""></p>
<h3 id="整堆收集器"><a href="#整堆收集器" class="headerlink" title="整堆收集器"></a>整堆收集器</h3><h4 id="7-G1收集器"><a href="#7-G1收集器" class="headerlink" title="7.G1收集器"></a>7.G1收集器</h4><p> G1收集器（Garbage-First）：是当今收集器技术发展的最前沿的成果之一，G1是一款面向服务器端应用的垃圾收集器。 使用G1收集器时，java堆的内存布局就与其他收集器有很大差别，它将真个java堆划分为多个大小相等的独立区域（Region），虽然还保留新生代与老年代的概念，但新生代与老年代不再试物理隔离的了，他们都是一部分Region（不需要连续）的集合。G1具备如下特点：</p>
<ul>
<li>并行与并发：G1能充分利用多CPU、多核环境下的硬件优势，使用多个CPU（CPU或者CPU核心）来缩短Stop-The-World停顿的时间，部分其他收集器原本需要停顿java线程执行的GC动作，G1收集器仍然可以通过并发的方式让java程序继续执行。</li>
<li>分代收集：与其他收集器一样，分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能够独立管理整个GC堆，但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。</li>
<li>空间整合：与CMS的“标记–清理”算法不同，G1从整体来看是基于“标记–整理”算法实现的收集器，从局部（两个Region之间）上来看是基于“复制”算法实现的，但无论如何，这两种算法都意味着G1运行期间不会产生内存空间碎片，收集后能提供规整的可用内存。这个特性有利于程序长时间运行，分配大对象时不会因为无法找到连续内存空间而提前出发下一次GC。</li>
<li>可预测的停顿：这是G1相对于CMS的另一大优势，降低停顿时间是G1和CMS共同的关注点，但G1除了追求低停顿外，还能建立可预测的停顿时间模型，能让使用者明确指定在一个长度为M毫秒的时间片段内，消耗在垃圾收集上的时间不得超过N毫秒，这几乎已经是实时java（RTSJ）的垃圾收集器的特性了。</li>
<li>初始标记（Initial Marking）：标记GC Roots能够直接关联到的对象，并且修改TAMS的值，能在正确可用的Region中创建对象，这阶段需要停顿线程，而且耗时很短。<br>并发标记（Concurrent Marking）：从GC Roots开始堆中对象进行可达性分析，找出存活的对象，这个时间耗时比较长，但可与用户程序并行执行。</li>
<li>最终标记（Final Marking）：为了修正和正在并发标记期间因用户程序继续运行而导致标记产生变动的那一部分没有标记记录，虚拟机将这一段对象变法记录在线程Rememberred Set logs里面，最终标记阶段需要把Remembered Set logs 的数据合并到Remembered Set中，这阶段需要停顿线程，但是可并发执行。</li>
<li>筛选回收（Live Data Counting and Evacuation）：对各个Region的回收截止和成本进行排序，根据用户期望的GC停顿时间来制定回收计划，这阶段可以做到和用户程序一起并发执行，但是因为值回收一部分Region，时间是用户可控制的，而且停顿用户线程将大幅度提高手机效率。</li>
</ul>
<h3 id="内存分配与回收策略"><a href="#内存分配与回收策略" class="headerlink" title="内存分配与回收策略"></a>内存分配与回收策略</h3><p>重点笔记：</p>
<ul>
<li>新生代GC（Minor GC）：发生在新生代的垃圾收集动作，非常频繁，一般回收速度也比较快。</li>
<li>老年代GC（Major GC/Full GC）：发生在老年代的垃圾收集动作，一般会伴随Minor GC 速度一般比Minor GC慢上10倍以上。</li>
</ul>
<ol>
<li><p>优先在Eden区分配（如果启动本地线程分配缓冲TLAB-Thread Local Allocation Buffer，则优先在TLAB）如果Eden区满，则触发一次Minor GC</p>
</li>
<li><p>大对象直接进入老年代；大对象，即大量连续内存空间的Java对象，最典型的是那种很长的字符串及数组。</p>
</li>
<li><p>长期存活的对象将进入老年代；设置对象年龄计数器。对象在Eden出生并经过第一次MinorGC后仍存活，年龄+1，移入Survivor区。以后每经过一次MinorGC年龄加一，当达到15时（默认的）就进入老年代</p>
</li>
<li><p>动态对象年龄判定，并不是对象年龄必须达到最大阈值才会进入老年代。如果survivor空间中相同年龄所有对象大小总和大于其空间的一般，年龄大于或等于该年龄的对象就可以直接进入老年代，无需等到阈值时才进入。</p>
</li>
<li><p>空间分配担保；发生minorGC之前，虚拟机先检查老年代最大可用的连续空间是否大于新生代所有对象总空间，成立，MinorGC可以确保是安全的。不成立，则检查HandlePromotionFailure设置值是否允许担保失败。允许，则检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小。大于将尝试MinorGC，小于或者不允许冒险，也要进行一次FullGC。老年代分配担保，将survivor无法容纳的对象直接进入老年代。依然担保失败，则只好在失败后重新发起一次Full GC。</p>
</li>
</ol>
<p>参考链接：</p>
<figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">https://blog.csdn.net/u013667756/article/details/82948012</span></span><br><span class="line"><span class="attribute">https://www.jianshu.com/p/9d09f93001e4</span></span><br><span class="line"><span class="attribute">https://blog.csdn.net/u012998254/article/details/81635902</span></span><br><span class="line"><span class="attribute">https://blog.csdn.net/u012998254/article/details/81635902</span></span><br></pre></td></tr></table></figure>

      
    </div>
    
    
    

    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>


      
    </div>   

    <div>
      
        
<div class="my_post_copyright">
  <script src="//cdn.bootcss.com/clipboard.js/1.5.10/clipboard.min.js"></script>
  
  <!-- JS库 sweetalert 可修改路径 -->
  <script src="https://cdn.bootcss.com/jquery/2.0.0/jquery.min.js"></script>
  <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
  <p><span>本文标题:</span><a href="/2019/08/29/垃圾收集器与内存分配策略-深入理解JVM/">垃圾收集器与内存分配策略-深入理解JVM</a></p>
  <p><span>文章作者:</span><a href="/" title="访问 zkstyle 的个人博客">zkstyle</a></p>
  <p><span>发布时间:</span>2019年08月29日 - 19:08</p>
  <p><span>最后更新:</span>2020年08月10日 - 14:08</p>
  <p><span>原始链接:</span><a href="/2019/08/29/垃圾收集器与内存分配策略-深入理解JVM/" title="垃圾收集器与内存分配策略-深入理解JVM">https://www.vazh.cn/2019/08/29/垃圾收集器与内存分配策略-深入理解JVM/</a>
    <span class="copy-path" title="点击复制文章链接"><i class="fa fa-clipboard" data-clipboard-text="https://www.vazh.cn/2019/08/29/垃圾收集器与内存分配策略-深入理解JVM/" aria-label="复制成功！"></i></span>
  </p>
  <p><span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p>  
</div>
<script> 
    var clipboard = new Clipboard('.fa-clipboard');
	  $(".fa-clipboard").click(function(){
      clipboard.on('success', function(){
        swal({   
          title: "",   
          text: '复制成功',
          icon: "success", 
          showConfirmButton: true
          });
	    });
    });  
</script>



      
    </div> 

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>坚持原创技术分享，您的支持将鼓励我继续创作！</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>赞赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/images/wechatpay.png" alt="zkstyle WeChat Pay">
        <p>WeChat Pay</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/images/alipay.jpg" alt="zkstyle Alipay">
        <p>Alipay</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/JVM/" rel="tag"><i class="fa fa-tag"></i> JVM</a>
          
            <a href="/tags/GC/" rel="tag"><i class="fa fa-tag"></i> GC</a>
          
            <a href="/tags/内存分配策略/" rel="tag"><i class="fa fa-tag"></i> 内存分配策略</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/08/29/Linux的文件权限与目录配置/" rel="next" title="Linux的文件权限与目录配置">
                <i class="fa fa-chevron-left"></i> Linux的文件权限与目录配置
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/09/04/Leetcode275-二叉树的所有路径/" rel="prev" title="Leetcode257-二叉树的所有路径">
                Leetcode257-二叉树的所有路径 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
        <!-- JiaThis Button BEGIN -->
<div class="jiathis_style">
  <a class="jiathis_button_tqq"></a>
  <a class="jiathis_button_weixin"></a>
  <a class="jiathis_button_cqq"></a>
  <a href="http://www.jiathis.com/share" class="jiathis jiathis_txt jiathis_separator jtico jtico_jiathis" target="_blank"></a>
  <a class="jiathis_counter_style"></a>
</div>
<script type="text/javascript">
  var jiathis_config={
    hideMore:false
  }
</script>
<script type="text/javascript" src="http://v3.jiathis.com/code/jia.js" charset="utf-8"></script>
<!-- JiaThis Button END -->

      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
      <div id="gitalk-container"></div>
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image" src="/images/zhihu02.jpg" alt="zkstyle">
          <p class="site-author-name" itemprop="name">zkstyle</p>
           
              <p class="site-description motion-element" itemprop="description">Stay hungry, stay foolish</p>
          
        </div>
        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
              <a href="/archives/">
                <span class="site-state-item-count">84</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">13</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">67</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        
          <div class="feed-link motion-element">
            <a href="/atom.xml" rel="alternate">
              <i class="fa fa-rss"></i>
              RSS
            </a>
          </div>
        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/zkstyle" target="_blank" title="Github">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                    
                      Github
                    
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://blog.csdn.net/zkhubu" target="_blank" title="csdn">
                  
                    <i class="fa fa-fw fa-crosshairs"></i>
                  
                    
                      csdn
                    
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://twitter.com/elvis03945040" target="_blank" title="Twitter">
                  
                    <i class="fa fa-fw fa-twitter"></i>
                  
                    
                      Twitter
                    
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://www.zhihu.com/people/huai-xiang-tian-kong-43/activities" target="_blank" title="Zhihu">
                  
                    <i class="fa fa-fw fa-spinner"></i>
                  
                    
                      Zhihu
                    
                </a>
              </span>
            
          
        </div>

        
        

        
        
          <div class="links-of-blogroll motion-element links-of-blogroll-inline">
            <div class="links-of-blogroll-title">
              <i class="fa  fa-fw fa-globe"></i>
              友情链接
            </div>
            <ul class="links-of-blogroll-list">
              
                <li class="links-of-blogroll-item">
                  <a href="http://jm.taobao.org/" title="Aliyun" target="_blank">Aliyun</a>
                </li>
              
                <li class="links-of-blogroll-item">
                  <a href="http://taobaofed.org/" title="taobao" target="_blank">taobao</a>
                </li>
              
            </ul>
          </div>
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#一-学习目标"><span class="nav-number">1.</span> <span class="nav-text">一 学习目标</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#二-那些内存需要回收"><span class="nav-number">2.</span> <span class="nav-text">二 那些内存需要回收</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#三-什么时候回收（判断对象的存活）"><span class="nav-number">3.</span> <span class="nav-text">三.什么时候回收（判断对象的存活）</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#引用计数算法"><span class="nav-number">3.1.</span> <span class="nav-text">引用计数算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#可达性分析算法"><span class="nav-number">3.2.</span> <span class="nav-text">可达性分析算法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#四-如何回收-垃圾收集算法"><span class="nav-number">4.</span> <span class="nav-text">四 如何回收-垃圾收集算法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-标记清除算法"><span class="nav-number">4.1.</span> <span class="nav-text">1.标记清除算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-复制算法"><span class="nav-number">4.2.</span> <span class="nav-text">2.复制算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-分代收集算法"><span class="nav-number">4.3.</span> <span class="nav-text">4.分代收集算法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#五-Hotspot算法实现及准确式GC"><span class="nav-number">5.</span> <span class="nav-text">五 Hotspot算法实现及准确式GC</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#对象的创建"><span class="nav-number">5.1.</span> <span class="nav-text">对象的创建</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-判断对象对应的类是否加载、链接、初始化"><span class="nav-number">5.1.1.</span> <span class="nav-text">1 判断对象对应的类是否加载、链接、初始化</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2为对象分配内存"><span class="nav-number">5.1.2.</span> <span class="nav-text">2为对象分配内存</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3处理并发安全问题"><span class="nav-number">5.1.3.</span> <span class="nav-text">3处理并发安全问题</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4初始化分配到的内存空间"><span class="nav-number">5.1.4.</span> <span class="nav-text">4初始化分配到的内存空间</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5设置对象的对象头"><span class="nav-number">5.1.5.</span> <span class="nav-text">5设置对象的对象头</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#6执行init方法进行初始化"><span class="nav-number">5.1.6.</span> <span class="nav-text">6执行init方法进行初始化</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HotSpot的对象模型"><span class="nav-number">5.2.</span> <span class="nav-text">HotSpot的对象模型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HotSpot的准确式GC"><span class="nav-number">5.3.</span> <span class="nav-text">HotSpot的准确式GC</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HotSpot安全点"><span class="nav-number">5.4.</span> <span class="nav-text">HotSpot安全点</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#抢先式中断"><span class="nav-number">5.5.</span> <span class="nav-text">抢先式中断</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#主动式中断"><span class="nav-number">5.6.</span> <span class="nav-text">主动式中断</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HotSpot安全区域"><span class="nav-number">5.7.</span> <span class="nav-text">HotSpot安全区域</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#六-七种垃圾收集器"><span class="nav-number">6.</span> <span class="nav-text">六 七种垃圾收集器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#新生代垃圾收集器"><span class="nav-number">6.1.</span> <span class="nav-text">新生代垃圾收集器</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-Serial收集器"><span class="nav-number">6.1.1.</span> <span class="nav-text">1.Serial收集器</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-ParNew收集器"><span class="nav-number">6.1.2.</span> <span class="nav-text">2.ParNew收集器</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-Parallel-Scavenge收集器"><span class="nav-number">6.1.3.</span> <span class="nav-text">3.Parallel Scavenge收集器</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#老年代垃圾收集器"><span class="nav-number">6.2.</span> <span class="nav-text">老年代垃圾收集器</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#4-Serial-Old收集器"><span class="nav-number">6.2.1.</span> <span class="nav-text">4.Serial Old收集器</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#5-Parallel-Old收集器"><span class="nav-number">6.2.2.</span> <span class="nav-text">5.Parallel Old收集器</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#6-CMS收集器"><span class="nav-number">6.2.3.</span> <span class="nav-text">6.CMS收集器</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#整堆收集器"><span class="nav-number">6.3.</span> <span class="nav-text">整堆收集器</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#7-G1收集器"><span class="nav-number">6.3.1.</span> <span class="nav-text">7.G1收集器</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#内存分配与回收策略"><span class="nav-number">6.4.</span> <span class="nav-text">内存分配与回收策略</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">
  
  &copy;  2018 - 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">zkstyle</span>
</div>

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>


<div class="powered-by">
<i class="fa fa-user-md"></i><span id="busuanzi_container_site_uv">
  本站总访问量:<span id="busuanzi_value_site_pv"></span>
</span>
</div>

  本站访问人数:<span id="busuanzi_value_site_uv"></span>


<div class="theme-info">
  <div class="powered-by"></div>
  <span class="post-count">博客全站共102.3k字</span>
</div>



        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>

  
  <script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.2"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.2"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.2"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.2"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.2"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.2"></script>



  


  




	





  





  






  <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
  <script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>
  <script src="/js/src/md5.min.js"></script>
   <script type="text/javascript">
        var gitalk = new Gitalk({
          clientID: '65fb17091a3360a3aff4',
          clientSecret: 'f0f4c5399cefc5ebf492861a6e38dfa920467e12',
          repo: 'zkstyle.github.io',
          owner: 'zkstyle',
          admin: ['zkstyle'],
           id: md5(location.pathname),
          distractionFreeMode: 'true'
        })
        gitalk.render('gitalk-container')           
       </script>



  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>
  <script>AV.initialize("1v0r5nCOvGl95iNsXltgjapB-gzGzoHsz", "rdy0TDJXds7aMJ3YrdrBqBeE");</script>
  <script>
    function showTime(Counter) {
      var query = new AV.Query(Counter);
      var entries = [];
      var $visitors = $(".leancloud_visitors");

      $visitors.each(function () {
        entries.push( $(this).attr("id").trim() );
      });

      query.containedIn('url', entries);
      query.find()
        .done(function (results) {
          var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

          if (results.length === 0) {
            $visitors.find(COUNT_CONTAINER_REF).text(0);
            return;
          }

          for (var i = 0; i < results.length; i++) {
            var item = results[i];
            var url = item.get('url');
            var time = item.get('time');
            var element = document.getElementById(url);

            $(element).find(COUNT_CONTAINER_REF).text(time);
          }
          for(var i = 0; i < entries.length; i++) {
            var url = entries[i];
            var element = document.getElementById(url);
            var countSpan = $(element).find(COUNT_CONTAINER_REF);
            if( countSpan.text() == '') {
              countSpan.text(0);
            }
          }
        })
        .fail(function (object, error) {
          console.log("Error: " + error.code + " " + error.message);
        });
    }

    function addCount(Counter) {
      var $visitors = $(".leancloud_visitors");
      var url = $visitors.attr('id').trim();
      var title = $visitors.attr('data-flag-title').trim();
      var query = new AV.Query(Counter);

      query.equalTo("url", url);
      query.find({
        success: function(results) {
          if (results.length > 0) {
            var counter = results[0];
            counter.fetchWhenSave(true);
            counter.increment("time");
            counter.save(null, {
              success: function(counter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(counter.get('time'));
              },
              error: function(counter, error) {
                console.log('Failed to save Visitor num, with error message: ' + error.message);
              }
            });
          } else {
            var newcounter = new Counter();
            /* Set ACL */
            var acl = new AV.ACL();
            acl.setPublicReadAccess(true);
            acl.setPublicWriteAccess(true);
            newcounter.setACL(acl);
            /* End Set ACL */
            newcounter.set("title", title);
            newcounter.set("url", url);
            newcounter.set("time", 1);
            newcounter.save(null, {
              success: function(newcounter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(newcounter.get('time'));
              },
              error: function(newcounter, error) {
                console.log('Failed to create');
              }
            });
          }
        },
        error: function(error) {
          console.log('Error:' + error.code + " " + error.message);
        }
      });
    }

    $(function() {
      var Counter = AV.Object.extend("Counter");
      if ($('.leancloud_visitors').length == 1) {
        addCount(Counter);
      } else if ($('.post-title-link').length > 1) {
        showTime(Counter);
      }
    });
  </script>



  

  

  

  

  

<script src="/live2dw/lib/L2Dwidget.min.js?0c58a1486de42ac6cc1c59c7d98ae887"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"/live2dw/assets/assets/shizuku.model.json"},"display":{"position":"right","width":150,"height":300},"mobile":{"show":false},"log":false});</script></body>
</html>
